From f20aa2a4601ca79ac3747617001fc46c1589a8fa Mon Sep 17 00:00:00 2001 From: robertl Date: Fri, 12 Sep 2008 15:18:08 +0000 Subject: [PATCH] Don Traber update Garmin Training Center to add read. Writes V2 format now. --- gtrnctr.c | 388 ++++++++++++++++++++++++++----------- internal_styles.c | 39 +++- xmldoc/formats/gtrnctr.xml | 38 +++- 3 files changed, 340 insertions(+), 125 deletions(-) diff --git a/gtrnctr.c b/gtrnctr.c index 296f6bef2..e09e20d11 100644 --- a/gtrnctr.c +++ b/gtrnctr.c @@ -25,42 +25,119 @@ static gbfile *ofd; static waypoint *wpt_tmp; static route_head *trk_head; +static computed_trkdata *tdata; #define MYNAME "gtc" +#define GTC_MAX_NAME_LEN 15 + +#define MAX_SPORTS 4 +static char gtc_sportlist[MAX_SPORTS][16] = { "Biking", "Running", "MultiSport", "Other" }; +static int gtc_sport = 0; +static int gtc_course_flag; + +static time_t gtc_least_time; +static time_t gtc_most_time; +static double gtc_start_lat; +static double gtc_start_long; +static double gtc_end_lat; +static double gtc_end_long; + +static char *opt_sport, *opt_course; + static arglist_t gtc_args[] = { + { "course", &opt_course, "Write course rather than history, default yes", + "1", ARGTYPE_BOOL, ARG_NOMINMAX}, + { "sport", &opt_sport, "Sport: Biking (deflt), Running, MultiSport, Other", + "Biking", ARGTYPE_STRING, ARG_NOMINMAX}, ARG_TERMINATOR }; -#if 0 + +#if ! HAVE_LIBEXPAT +static void +gtc_rd_init(const char *fname) +{ + fatal(MYNAME ": this format does not support reading.\n"); +} + +static void +gtc_read(void) +{ +} +#else + /* Tracks */ -static xg_callback gl_trk_s; -// static xg_callback gl_trk_ident; -static xg_callback gl_trk_pnt_s, gl_trk_pnt_e; -static xg_callback gl_trk_utc; -static xg_callback gl_trk_lat; -static xg_callback gl_trk_long; -static xg_callback gl_trk_alt; - -static xg_tag_mapping gl_map[] = { - { gl_trk_s, cb_start, "/History/Run/Track" }, - { gl_trk_pnt_s,cb_start, "/History/Run/Track/Trackpoint/Position" }, - { gl_trk_pnt_e,cb_end, "/History/Run/Track/Trackpoint/Position" }, - { gl_trk_lat, cb_cdata, "/History/Run/Track/Trackpoint/Position/Latitude" }, - { gl_trk_long, cb_cdata, "/History/Run/Track/Trackpoint/Position/Longitude" }, - { gl_trk_alt, cb_cdata, "/History/Run/Track/Trackpoint/Position/Altitude" }, - { gl_trk_utc, cb_cdata, "/History/Run/Track/Trackpoint/Time" }, - { NULL, 0, NULL} +static xg_callback gtc_trk_s; +static xg_callback gtc_trk_ident; +static xg_callback gtc_trk_pnt_s, gtc_trk_pnt_e; +static xg_callback gtc_trk_utc; +static xg_callback gtc_trk_lat; +static xg_callback gtc_trk_long; +static xg_callback gtc_trk_alt; +static xg_callback gtc_trk_hr; +static xg_callback gtc_trk_cad; + +static xg_tag_mapping gtc_map[] = { + /* courses tcx v1 & v2 */ + { gtc_trk_s, cb_start, "/Courses/Course" }, + { gtc_trk_ident,cb_cdata, "/Courses/Course/Name"}, + { gtc_trk_pnt_s,cb_start, "/Courses/Course/Track/Trackpoint" }, + { gtc_trk_pnt_e,cb_end, "/Courses/Course/Track/Trackpoint" }, + { gtc_trk_utc, cb_cdata, "/Courses/Course/Track/Trackpoint/Time" }, + { gtc_trk_lat, cb_cdata, "/Courses/Course/Track/Trackpoint/Position/LatitudeDegrees" }, + { gtc_trk_long, cb_cdata, "/Courses/Course/Track/Trackpoint/Position/LongitudeDegrees" }, + { gtc_trk_alt, cb_cdata, "/Courses/Course/Track/Trackpoint/AltitudeMeters" }, + { gtc_trk_alt, cb_cdata, "/Courses/Course/Track/Trackpoint/AltitudeMeters" }, + { gtc_trk_hr, cb_cdata, "/Courses/Course/Track/Trackpoint/HeartRateBpm" }, + { gtc_trk_cad, cb_cdata, "/Courses/Course/Track/Trackpoint/Cadence" }, + + /* history tcx v2 (activities) */ + { gtc_trk_s, cb_start, "/Activities/Activity" }, + { gtc_trk_ident,cb_cdata, "/Activities/Activity/Id" }, + { gtc_trk_pnt_s,cb_start, "/Activities/Activity/Track/Trackpoint" }, + { gtc_trk_pnt_e,cb_end, "/Activities/Activity/Track/Trackpoint" }, + { gtc_trk_utc, cb_cdata, "/Activities/Activity/Track/Trackpoint/Time" }, + { gtc_trk_lat, cb_cdata, "/Activities/Activity/Track/Trackpoint/Position/LatitudeDegrees" }, + { gtc_trk_long, cb_cdata, "/Activities/Activity/Track/Trackpoint/Position/LongitudeDegrees" }, + { gtc_trk_alt, cb_cdata, "/Activities/Activity/Track/Trackpoint/AltitudeMeters" }, + { gtc_trk_hr, cb_cdata, "/Activities/Activity/Track/Trackpoint/HeartRateBpm" }, + { gtc_trk_cad, cb_cdata, "/Activities/Activity/Track/Trackpoint/Cadence" }, + + /* history tcx v1 */ + { gtc_trk_s, cb_start, "/History/Run" }, + { gtc_trk_ident,cb_cdata, "/History/Run/Id" }, + { gtc_trk_pnt_s,cb_start, "/History/Run/Track/Trackpoint" }, + { gtc_trk_pnt_e,cb_end, "/History/Run/Track/Trackpoint" }, + { gtc_trk_utc, cb_cdata, "/History/Run/Track/Trackpoint/Time" }, + { gtc_trk_lat, cb_cdata, "/History/Run/Track/Trackpoint/Position/LatitudeDegrees" }, + { gtc_trk_long, cb_cdata, "/History/Run/Track/Trackpoint/Position/LongitudeDegrees" }, + { gtc_trk_alt, cb_cdata, "/History/Run/Track/Trackpoint/AltitudeMeters" }, + { gtc_trk_hr, cb_cdata, "/History/Run/Track/Trackpoint/HeartRateBpm" }, + { gtc_trk_cad, cb_cdata, "/History/Run/Track/Trackpoint/Cadence" }, + + { NULL, 0, NULL} +}; + +static const char * +gtc_tags_to_ignore[] = { + "TrainingCenterDatabase", + "Lap", + "CourseFolder", + "Running", + "Biking", + "Other", + "Multisport", + NULL, }; -#endif static void gtc_rd_init(const char *fname) { - fatal(MYNAME ": this format does not support reading.\n"); + xml_init(fname, gtc_map, NULL); + xml_ignore_tags(gtc_tags_to_ignore); } -#if 0 static void gtc_read(void) { @@ -77,16 +154,30 @@ gtc_rd_deinit(void) static void gtc_wr_init(const char *fname) { + int i; + ofd = gbfopen(fname, "w", MYNAME); + + if(opt_sport) { + for(i = 0; i < MAX_SPORTS; i++) { + if(0 == case_ignore_strncmp(opt_sport, gtc_sportlist[i], 2)) { + gtc_sport = i; + break; + } + } + } + gtc_course_flag = atoi(opt_course); } static void gtc_wr_deinit(void) { gbfclose(ofd); + xfree(tdata); } static int gtc_indent_level; + static void gtc_write_xml(int indent, const char *fmt, ...) { @@ -107,32 +198,19 @@ gtc_write_xml(int indent, const char *fmt, ...) static void gtc_waypt_pr(const waypoint *wpt) { -#if 0 - gbfprintf(ofd, " \n"); - gbfprintf(ofd, " \n"); - gbfprintf(ofd, " %.5f\n", wpt->latitude); - gbfprintf(ofd, " %.5f\n", wpt->longitude); - if (wpt->altitude != unknown_alt) { - gbfprintf(ofd, " %.3f\n", wpt->altitude); + if (wpt->wpt_flags.is_split != 0) { + gtc_write_xml(1, "\n"); + } else { + gtc_write_xml(1, "\n"); } - gbfprintf(ofd, " \n"); - gbfprintf(ofd, " "); - xml_write_time(ofd, wpt->creation_time, "Time"); - gbfprintf(ofd, " \n"); -#else - if (wpt->wpt_flags.is_split != 0) { - gtc_write_xml(1, "\n"); - } else { - gtc_write_xml(1, "\n"); - } if (wpt->creation_time) { char time_string[100]; xml_fill_in_time(time_string, wpt->creation_time, wpt->microseconds, - XML_LONG_TIME); + XML_LONG_TIME); if (time_string[0]) { gtc_write_xml(0, "\n", - time_string); + time_string); } } gtc_write_xml(1, "\n"); @@ -143,31 +221,116 @@ gtc_waypt_pr(const waypoint *wpt) gtc_write_xml(0, "%f\n", wpt->altitude); } if (wpt->heartrate) { - gtc_write_xml(0, "%d\n", wpt->heartrate); + //gtc_write_xml(0, "%d\n", wpt->heartrate); + gtc_write_xml(1, "\n"); + gtc_write_xml(0,"%d\n", wpt->heartrate); + gtc_write_xml(-1,"\n"); } - if (wpt->cadence) { + if (wpt->cadence) { gtc_write_xml(0, "%d\n", wpt->cadence); } - gtc_write_xml(-1, "\n"); -#endif } static void -gtc_hdr( const route_head *rte) +gtc_fake_hdr(void) +{ + long secs = 0; + if (gtc_least_time && gtc_most_time) { + secs = gtc_most_time - gtc_least_time; + } + if(gtc_course_flag) { /* course format */ + + gtc_write_xml(0, "%d\n", secs); + gtc_write_xml(0, "%lf\n", + tdata->distance_meters ? tdata->distance_meters : 0); + gtc_write_xml(1, "\n"); + gtc_write_xml(0, "%lf\n", gtc_start_lat); + gtc_write_xml(0, "%lf\n", gtc_start_long); + gtc_write_xml(-1, "\n"); + gtc_write_xml(1, "\n"); + gtc_write_xml(0, "%lf\n", gtc_end_lat); + gtc_write_xml(0, "%lf\n", gtc_end_long); + gtc_write_xml(-1, "\n"); + gtc_write_xml(1, "\n"); + gtc_write_xml(0,"%g\n", + tdata->avg_hrt ? tdata->avg_hrt : 100); + gtc_write_xml(-1, "\n"); + gtc_write_xml(1, "\n"); + gtc_write_xml(0,"%d\n", + tdata->max_hrt ? tdata->max_hrt : 200); + gtc_write_xml(-1,"\n"); + gtc_write_xml(0, "Active\n"); + + } else { /* activity (history) format */ + + gtc_write_xml(0, "%d\n", secs); + gtc_write_xml(0, "%lf\n", + tdata->distance_meters ? tdata->distance_meters : 1000); + gtc_write_xml(0, "0\n"); + gtc_write_xml(0, "0\n"); + gtc_write_xml(1, "\n"); + gtc_write_xml(0,"%g\n", + tdata->avg_hrt ? tdata->avg_hrt : 100); + gtc_write_xml(-1, "\n"); + gtc_write_xml(1, "\n"); + gtc_write_xml(0,"%d\n", + tdata->max_hrt ? tdata->max_hrt : 200); + gtc_write_xml(-1,"\n"); + gtc_write_xml(0, "Active\n"); + gtc_write_xml(0, "Manual\n"); + } +} + +static void +gtc_act_hdr( const route_head *rte) { + gtc_write_xml(1, "\n", gtc_sportlist[gtc_sport]); + if (gtc_least_time) { + char time_string[100]; + xml_fill_in_time(time_string, gtc_least_time, 0, XML_LONG_TIME); + gtc_write_xml(0, "%s\n", time_string); + gtc_write_xml(1, "\n", time_string); + } else { + gtc_write_xml(1, "\n"); + } + gtc_fake_hdr(); gtc_write_xml(1,"\n"); } static void -gtc_ftr(const route_head *rte) +gtc_act_ftr(const route_head *rte) { - gtc_write_xml(-1,"\n"); + gtc_write_xml(-1, "\n"); + gtc_write_xml(-1, "\n"); + gtc_write_xml(-1, "\n"); } -static time_t gtc_least_time; -static time_t gtc_most_time; +static void +gtc_crs_hdr( const route_head *rte) +{ + + gtc_write_xml(1, "\n"); + if(rte->rte_name) { + gtc_write_xml(0, "%s\n", xstrndup(rte->rte_name, GTC_MAX_NAME_LEN)); + } else { + gtc_write_xml(0, "New Course\n"); + } + /* write_optional_xml_entity(ofd, " ", "Name", rte->rte_name); */ + gtc_write_xml(1, "\n"); + gtc_fake_hdr(); + gtc_write_xml(-1, "\n"); + gtc_write_xml(1,"\n"); +} + +static void +gtc_crs_ftr(const route_head *rte) +{ + gtc_write_xml(-1,"\n"); + gtc_write_xml(-1, "\n"); + +} static void gtc_lap_start(const route_head *rte) @@ -177,131 +340,130 @@ gtc_lap_start(const route_head *rte) } static void -gtc_study_lap(const waypoint *wpt) +gtc_new_study_lap(const route_head *rte) { - if (wpt->creation_time && (gtc_least_time == 0)) - gtc_least_time = wpt->creation_time; - - if (wpt->creation_time && (gtc_least_time > wpt->creation_time)) - gtc_least_time = wpt->creation_time; - - if (wpt->creation_time > gtc_most_time) - gtc_most_time = wpt->creation_time; + track_recompute(rte, &tdata); /* called routine allocates space for tdata */ } static void -gtc_fake_hdr(void) +gtc_study_lap(const waypoint *wpt) { - long secs = 0; - if (gtc_least_time && gtc_most_time) { - secs = gtc_most_time - gtc_least_time; + if (wpt->creation_time && (gtc_least_time == 0)) { + gtc_least_time = wpt->creation_time; + gtc_start_lat = wpt->latitude; + gtc_start_long = wpt->longitude; + } + + if (wpt->creation_time && (gtc_least_time > wpt->creation_time)) { + gtc_least_time = wpt->creation_time; + gtc_start_lat = wpt->latitude; + gtc_start_long = wpt->longitude; + } + if (wpt->creation_time > gtc_most_time) { + gtc_most_time = wpt->creation_time; + gtc_end_lat = wpt->latitude; + gtc_end_long = wpt->longitude; } - gtc_write_xml(0, "%d\n", secs); - gtc_write_xml(0, "0\n"); - gtc_write_xml(0, "0\n"); - gtc_write_xml(0, "0\n"); - gtc_write_xml(0, "0\n"); - gtc_write_xml(0, "Active\n"); - gtc_write_xml(0, "Manual\n"); } void gtc_write(void) { -#if 0 - gbfprintf(ofd, "\n"); - gbfprintf(ofd, "\n"); - gbfprintf(ofd, " \n"); - track_disp_all(gtc_hdr, gtc_ftr, gtc_waypt_pr); - gbfprintf(ofd, " \n"); - gbfprintf(ofd, "\n"); -#else gtc_write_xml(0, "\n"); - gtc_write_xml(1, "\n"); - gtc_write_xml(1, "\n"); - - gtc_write_xml(1, "\n"); - gtc_write_xml(1, "\n"); + gtc_write_xml(1, "\n"); gtc_lap_start(NULL); track_disp_all(NULL, NULL, gtc_study_lap); + track_disp_all(gtc_new_study_lap, NULL, NULL); - if (gtc_least_time) { - char time_string[100]; - xml_fill_in_time(time_string, gtc_least_time, 0, XML_LONG_TIME); - gtc_write_xml(1, "\n", time_string); + if(gtc_course_flag) { + gtc_write_xml(1, "\n"); + track_disp_all(gtc_crs_hdr, gtc_crs_ftr, gtc_waypt_pr); + gtc_write_xml(-1, "\n"); } else { - gtc_write_xml(1, "\n"); + gtc_write_xml(1, "\n"); + track_disp_all(gtc_act_hdr, gtc_act_ftr, gtc_waypt_pr); + gtc_write_xml(-1, "\n"); } - gtc_fake_hdr(); - track_disp_all(gtc_hdr, gtc_ftr, gtc_waypt_pr); - gtc_write_xml(-1, "\n"); - gtc_write_xml(-1, "\n"); - gtc_write_xml(-1, "\n"); - gtc_write_xml(0, "\n"); - gtc_write_xml(0, "\n"); - gtc_write_xml(0, "\n"); - gtc_write_xml(-1, "\n"); gtc_write_xml(-1, "\n"); - -#endif } -void gl_trk_s(const char *args, const char **unused) +void +gtc_trk_s(const char *unused, const char **attrv) { trk_head = route_head_alloc(); track_add_head(trk_head); } -#if 0 -void gl_trk_ident(const char *args, const char **unused) + +void +gtc_trk_ident(const char *args, const char **unused) { trk_head->rte_name = xstrdup(args); } -#endif -void gl_trk_pnt_s(const char *args, const char **unused) +void +gtc_trk_pnt_s(const char *unused, const char **attrv) { wpt_tmp = waypt_new(); } -void gl_trk_pnt_e(const char *args, const char **unused) +void +gtc_trk_pnt_e(const char *args, const char **unused) { - track_add_wpt(trk_head, wpt_tmp); + if(wpt_tmp->longitude != 0. && wpt_tmp->latitude != 0.) track_add_wpt(trk_head, wpt_tmp); } -void gl_trk_utc(const char *args, const char **unused) +void +gtc_trk_utc(const char *args, const char **unused) { wpt_tmp->creation_time = xml_parse_time(args, NULL); } -void gl_trk_lat(const char *args, const char **unused) +void +gtc_trk_lat(const char *args, const char **unused) { wpt_tmp->latitude = atof(args); } -void gl_trk_long(const char *args, const char **unused) +void +gtc_trk_long(const char *args, const char **unused) { wpt_tmp->longitude = atof(args); } -void gl_trk_alt(const char *args, const char **unused) +void +gtc_trk_alt(const char *args, const char **unused) { wpt_tmp->altitude = atof(args); } +void +gtc_trk_hr(const char *args, const char **unused) +{ + wpt_tmp->heartrate = atoi(args); +} +void +gtc_trk_cad(const char *args, const char **unused) +{ + wpt_tmp->cadence = atoi(args); +} ff_vecs_t gtc_vecs = { ff_type_file, - { ff_cap_none, ff_cap_write, ff_cap_none}, + { + ff_cap_none /* waypoints */, + ff_cap_read | ff_cap_write /* tracks */, + ff_cap_none /* routes */ + }, gtc_rd_init, gtc_wr_init, - NULL, + gtc_rd_deinit, gtc_wr_deinit, - NULL, + gtc_read, gtc_write, - NULL, + NULL, gtc_args, CET_CHARSET_ASCII, 0 /* CET-REVIEW */ }; diff --git a/internal_styles.c b/internal_styles.c index 32578b445..3b0539372 100644 --- a/internal_styles.c +++ b/internal_styles.c @@ -512,6 +512,41 @@ static char iblue747[] = "IFIELD PATH_SPEED_KPH,\"\",\"%.1f\" # SPEED\n" "IFIELD PATH_DISTANCE_KM,\"\",\"%f\" # DISTANCE\n" ; +static char igo2008_poi[] = +"# gpsbabel XCSV style file\n" +"#\n" +"# Format: iGO2008 points of interest\n" +"# Author: Olaf Klein\n" +"# Date: 09/05/2008\n" +"#\n" +"DESCRIPTION iGO2008 points of interest (.upoi)\n" +"EXTENSION upoi\n" +"DATATYPE WAYPOINT\n" +"#\n" +"# FILE LAYOUT DEFINITIIONS:\n" +"#\n" +"FIELD_DELIMITER PIPE\n" +"RECORD_DELIMITER CRNEWLINE\n" +"BADCHARS \"|\n" +"ENCODING MS-ANSI\n" +"#\n" +"# INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE:\n" +"#\n" +"IFIELD INDEX,\"1\",\"%d\"\n" +"IFIELD DESCRIPTION, \"\", \"%s\"\n" +"IFIELD SHORTNAME, \"\", \"%s\"\n" +"IFIELD IGNORE, \"\", \"%s\" # nothing\n" +"IFIELD LAT_DECIMAL, \"\", \"%.6f\"\n" +"IFIELD LON_DECIMAL, \"\", \"%.6f\"\n" +"IFIELD IGNORE, \"\", \"%s\" # Name of map\n" +"IFIELD IGNORE, \"\", \"%s\" # nothing\n" +"IFIELD POSTAL_CODE, \"\", \"%s\"\n" +"IFIELD CITY, \"\", \"%s\"\n" +"IFIELD STREET_ADDR, \"\", \"%s\" # Street without number\n" +"IFIELD IGNORE, \"\", \"%s\" # Street number\n" +"IFIELD NOTES, \"\", \"%s\"\n" +"IFIELD PHONE_NR, \"\", \"%s\"\n" +; static char kompass_tk[] = "# gpsbabel XCSV style file\n" "#\n" @@ -1180,8 +1215,8 @@ static char xmapwpt[] = "IFIELD IGNORE, \"\", \"%-.31s\"\n" "IFIELD DESCRIPTION, \"\", \"%-.78s\"\n" ; -style_vecs_t style_list[] = {{ "xmapwpt", xmapwpt } , { "xmap2006", xmap2006 } , { "xmap", xmap } , { "tomtom_itn", tomtom_itn } , { "tomtom_asc", tomtom_asc } , { "tabsep", tabsep } , { "sportsim", sportsim } , { "saplus", saplus } , { "s_and_t", s_and_t } , { "openoffice", openoffice } , { "nima", nima } , { "navigonwpt", navigonwpt } , { "mxf", mxf } , { "mapconverter", mapconverter } , { "kwf2", kwf2 } , { "ktf2", ktf2 } , { "kompass_wp", kompass_wp } , { "kompass_tk", kompass_tk } , { "iblue747", iblue747 } , { "gpsman", gpsman } , { "gpsdrivetrack", gpsdrivetrack } , { "gpsdrive", gpsdrive } , { "geonet", geonet } , { "garmin_poi", garmin_poi } , { "garmin301", garmin301 } , { "fugawi", fugawi } , { "dna", dna } , { "custom", custom } , { "cup", cup } , { "csv", csv } , { "cambridge", cambridge } , { "arc", arc } , {0,0}}; -size_t nstyles = 32; +style_vecs_t style_list[] = {{ "xmapwpt", xmapwpt } , { "xmap2006", xmap2006 } , { "xmap", xmap } , { "tomtom_itn", tomtom_itn } , { "tomtom_asc", tomtom_asc } , { "tabsep", tabsep } , { "sportsim", sportsim } , { "saplus", saplus } , { "s_and_t", s_and_t } , { "openoffice", openoffice } , { "nima", nima } , { "navigonwpt", navigonwpt } , { "mxf", mxf } , { "mapconverter", mapconverter } , { "kwf2", kwf2 } , { "ktf2", ktf2 } , { "kompass_wp", kompass_wp } , { "kompass_tk", kompass_tk } , { "igo2008_poi", igo2008_poi } , { "iblue747", iblue747 } , { "gpsman", gpsman } , { "gpsdrivetrack", gpsdrivetrack } , { "gpsdrive", gpsdrive } , { "geonet", geonet } , { "garmin_poi", garmin_poi } , { "garmin301", garmin301 } , { "fugawi", fugawi } , { "dna", dna } , { "custom", custom } , { "cup", cup } , { "csv", csv } , { "cambridge", cambridge } , { "arc", arc } , {0,0}}; +size_t nstyles = 33; #else /* CSVFMTS_ENABLED */ style_vecs_t style_list[] = {{0,0}}; size_t nstyles = 0; diff --git a/xmldoc/formats/gtrnctr.xml b/xmldoc/formats/gtrnctr.xml index 34c59528d..37f02c9bd 100644 --- a/xmldoc/formats/gtrnctr.xml +++ b/xmldoc/formats/gtrnctr.xml @@ -1,16 +1,34 @@ -GPSBabel has limited support for Garmin Training Center files. That program is the successor to Garmin' Logbook program for their workout units. It is a free upgrade. +GPSBabel supports reading and writing of tracks in the .tcx +format used by Garmin Training Center (GTC). GTC is the successor +to Garmin's Logbook program for their workout units. It is a +free upgrade. -This format is somewhat underachieving in GPSBabel. It is a write-only -format; we never read it. The bigger problem, however, is a fundamental -impedance mismatch between this format and most of what we support. GPSBabel -fundamentally deals in waypoints, tracks, and routes. While we do record -things like heart rate and temperature when we know it, the fundamentals -of Training Center are different - it deals in concepts like laps and calories -which are rather alien to GPSBabel and most of the formats we support. As -such, while we can describe the tracks pretty accurately, things like -calories and heart zone tracking are not supported. +GPSBabel can read GTC .tcx v1 and v2 files, and can write v2 files. +There is a fundamental mismatch between this format and most of +what we support. GPSBabel deals in waypoints, tracks, and routes. +While we do record things like heart rate and temperature when we know +it, the fundamentals of Training Center are different. It deals in +concepts like laps and calories, which are rather alien to GPSBabel +and most of the formats we support. As such, while we can describe +the tracks pretty accurately, things like calories and heart zone +tracking are not supported. + +One of the most useful things you can do with this format is to send +.tcx files found on the web or elsewhere to any supported GPS +unit. You will probably want to include the transform (rte=trk) +and simplify filters in this process. For example, + + +gpsbabel -i gtrnctr -f somefile.tcx -x simplify,count=50 +-x transform,rte=trk -r -o garmin -F usb: + + +where you select the count not to exceed the number of available +waypoints for routing on your device. + + -- 2.30.2